// OpentTxl-C Version 11 safe C dynamic arrays
// Copyright 2024, James R. Cordy and others

// Standard C library
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
    #include <malloc.h>
#endif

// Check interface consistency
#include "alloc.h"

// Allocated array table
static void * taarrays[tamaxArrays];
static int tanextarray;

// Safe array allocation
void * taarrayalloc (const int size, const int typesize)
{ 
    void * arrayptr = NULL;
    if (tanextarray < tamaxArrays) {
        arrayptr = (void *) (calloc(size, typesize));
        taarrays[tanextarray] = arrayptr;
        tanextarray++;
    }
    if (arrayptr == NULL) {
        fprintf (stderr, "TXL ERROR : (Fatal) Available heap space too small for TXL heap\n"); \
        exit (1);
    } else {
        return (arrayptr);
    }
}

// Safe nonscalar copy
void arraycpy (const void *dest, const void *src, unsigned int size) 
{
    // If we have a long aligned copy, do it in longs
    if ((size > sizeof (long)) 
            && (size % sizeof (long) == 0) 
            && ((unsigned long long) dest % sizeof (long) == 0) 
            && ((unsigned long long) src % sizeof (long) == 0)) {
        long *d = (long *) dest;
        const long *s = (long *) src;

        // One long at a time
        for (int i = 0; i < (size / sizeof (long)); i++) {
            d[i] = s[i];
        }

    // Otherwise we must do bytes
    } else {
        char *d = (char *) dest;
        const char *s = (char *) src;

        // One byte at a time
        for (int i = 0; i < size; i++) {
            d[i] = s[i];
        }
    }
}

// Support routines
void tainitialize (void)
{
    for (int i = 0; i < tamaxArrays; i++) {
        taarrays[i] = NULL;
    }
    tanextarray = 0;
}

void tafinalize (void)
{
    // Free all allocated arrays
    for (int i = 0; i < tanextarray; i++) {
        if (taarrays[i] != NULL) {
            free (taarrays[i]);
        }
    }
}
